package com.example.academic_affairs_system.common;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.example.academic_affairs_system.model.dto.PageDTO;
import com.fasterxml.jackson.annotation.JsonInclude;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.util.List;

/**
 * 分页返回结果
 *
 * @author hjx
 * @since 2023/02/04 9:50 AM
 */
@Data
@NoArgsConstructor
@AllArgsConstructor
@JsonInclude(JsonInclude.Include.NON_NULL)
@ApiModel("分页返回结果")
public class RPage<T> {
  @ApiModelProperty("当前页码")
  long currentPage;

  @ApiModelProperty("当前截取数量")
  long limit;

  @ApiModelProperty("数据总量")
  long total;

  @ApiModelProperty("总页码")
  long totalPage;

  @ApiModelProperty("分页数据")
  List<T> data;

  public static <T> RPageBuilder<T> createDto(PageDTO dto) {
    return RPage.<T>builder().currentPage(dto.getPage()).limit(dto.getLimit());
  }

  public static <T> RPageBuilder<T> builder() {
    return new RPageBuilder<>();
  }

  public static final class RPageBuilder<T> {
    long currentPage;
    long limit;
    long total;
    long totalPage;
    List<T> data;

    @FunctionalInterface
    public interface ExecuteHandler<T> {
      List<T> execute(IPage<T> page);
    }

    private RPageBuilder() {}

    public RPageBuilder<T> currentPage(long currentPage) {
      this.currentPage = currentPage;
      return this;
    }

    public RPageBuilder<T> limit(long limit) {
      this.limit = limit;
      return this;
    }

    public RPageBuilder<T> data(List<T> data) {
      this.data = data;
      return this;
    }

    public RPageBuilder<T> execute(ExecuteHandler<T> handler) {
      Page<T> page = new Page<>(currentPage, limit);
      this.data = handler.execute(page);
      this.total = page.getTotal();
      this.currentPage = page.getCurrent();
      this.limit = page.getSize();
      if (total > 0 && limit > 0) {
        totalPage = (long) Math.ceil((double) total / this.limit);
      }
      return this;
    }

    public RPage<T> build() {
      return new RPage<>(currentPage, limit, total, totalPage, data);
    }
  }
}
